#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cmath>
#include <vector>

#include <timer.h>
#include <util.h>

using namespace std;

/** NOTE: Esto tiene que ser una copia exacta de ej2.cpp */
typedef float prec_t;
typedef unsigned long long int entero_t;

struct Circulo {
	entero_t r;
	entero_t d;

	Circulo( entero_t d, entero_t r ) {
		this->d = d;
		this->r = r;
	}
};

struct Intervalo {
	prec_t a, b;
	
	Intervalo( prec_t a = 0.0, prec_t b = 0.0 ) {
		this->a = a;
		this->b = b;
	}

	bool operator< ( const Intervalo &otro ) const {
		return a < otro.a;
	}
};

extern int resolverProblema( const vector< Circulo > &circulos, int l, int w );

/** Acá empieza el generador. **/
static int gMin = 1;
static int gMax = 100000;

void generarMejorCaso( ostream &salida ) {
	vector< Circulo > circulos;
	Timer t;
	
	ofstream times( "t2-times-mejor.txt" );
	ofstream clocks( "t2-clocks-mejor.txt" );
	
	// El mejor caso, quedarse con una lista de 0 elementos...
	for ( int i = gMin; i <= gMax; i++ ) {
		for ( int j = 0; j < i; j++ ) {
			circulos.push_back( Circulo( 10, 5 ) );
		}
		t.comenzar();
		resolverProblema( circulos, 20, 20 );
		t.terminar();
	
		times << i << ' ' << t.getTiempo() << endl;
		clocks << i << ' ' << t.getCiclos() << endl;
		
		circulos.clear();
	}
}

void generarPeorCaso( ostream &salida ) {
	vector< Circulo > circulos;
	Timer t;
	
	ofstream times( "t2-times-peor.txt" );
	ofstream clocks( "t2-clocks-peor.txt" );
	
	// El peor caso es cuando recorre TODOS los elementos
	// más haya de si tiene solución o no.
	for ( int i = gMin; i <= gMax; i++ ) {
		for ( int j = 0; j < i; j++ ) {
			circulos.push_back( Circulo( i - j - 1, 2 ) );
		}
		
		t.comenzar();
		resolverProblema( circulos, i, 1 );
		t.terminar();
	
		times << i << ' ' << t.getTiempo() << endl;
		clocks << i << ' ' << t.getCiclos() << endl;
		
		circulos.clear();
	}
}

void generarCasosAleatorios( ostream &salida ) {
	vector< Circulo > circulos;
	Timer t;
	
	ofstream times( "t2-times-aleatorio.txt" );
	ofstream clocks( "t2-clocks-aleatorio.txt" );
	
	srand( time( 0 ) );
	
	for ( int i = gMin; i <= gMax; i++ ) {
		int w = 3 + rand() % 70;
		int l = 3 + rand() % 2000;
	
		for ( int j = 0; j < i; j++ ) {
			circulos.push_back( Circulo( rand() % l, rand() % (4*w) ) );
		}
		
		t.comenzar();
		resolverProblema( circulos, l, w );
		t.terminar();
	
		times << i << ' ' << t.getTiempo() << endl;
		clocks << i << ' ' << t.getCiclos() << endl;
		
		circulos.clear();
	}
}

bool establecerMaximo( const char *str ) {
	if ( !str2int( str, &gMax ) ) {
		cerr << "Máximo no reconocido, debe ser un número entero.\n";
		return false;
	}
	return true;
}

bool establecerMinimo( const char *str ) {
	if ( !str2int( str, &gMin ) ) {
		cerr << "Mínimo no reconocido, debe ser un número entero.\n";
		return false;
	}
	return true;
}
